package com.mbschenkel.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.mbschenkel.client.Hash;
import com.mbschenkel.client.LatexService;
import com.mbschenkel.client.SessionData;
import com.mbschenkel.client.SnippetList;
import com.mbschenkel.client.SnippetStruct;

import java.sql.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class LatexServiceImpl extends RemoteServiceServlet implements LatexService {
  private HttpSession getSession() {
	  // Get the current request and then return its session
	  return this.getThreadLocalRequest().getSession();
	  /* could be used somewhere on the server as follows:
	   * 		latexService.getSession();
		public LatexServiceImpl() {
			HttpServletRequest request = this.getThreadLocalRequest();
			httpSession = request.getSession();
		}
		// TODO implement job-processing thread in init() method here
	   */
  }
	  
  public String myMethod(String s) {
	  return s;
	  // not impl. so far - used for testing
  }
  
 public String queryJob(SessionData.SessionVerificationData sessionVerificationData, String jobID){
	  if( !verifySession(sessionVerificationData) ) {
		  return null;
	  }
	  
	  LatexRenderer renderer = new LatexRenderer();
	  return renderer.queryJob(jobID);
 }
 
 public String processJob(SessionData.SessionVerificationData sessionVerificationData, String jobID) {
	  if( !verifySession(sessionVerificationData) ) {
		  return null;
	  }
	  
	  LatexRenderer renderer = new LatexRenderer();
	  renderer.processJob(jobID);
	  return "Job processed";
 }
 
 /**
  * Add a full job to the job queue
  */
  public String renderFull(SessionData.SessionVerificationData sessionVerificationData, String s) {
	  if( !verifySession(sessionVerificationData) ) {
		  return null;
	  }
	  
	  LatexRenderer renderer = new LatexRenderer();
	  String jobID = renderer.addJob( s, LatexRenderer.jobTypeStrFull );
	  System.out.println( "Job created : "+jobID);
	  return jobID;
  }
  
  public com.mbschenkel.client.SnippetStruct loadSnippet(SessionData.SessionVerificationData sessionVerificationData,int snippetID) {
	  if( !verifySession(sessionVerificationData) ) {
		  // dont fail without session 
		  //return null;
	  }
	  
	  LatexRenderer renderer = new LatexRenderer();
	  return renderer.loadSnippet(snippetID);
		 /*
	  SnippetStruct snip = new SnippetStruct();
	  snip.url = "http://";
	  snip.command = "\\test";
	  snip.tryReload = false;
	  snip.id = 1;
	  return snip;
	  */
  }
  
  public SnippetList loadSnippetList(SessionData.SessionVerificationData sessionVerificationData) {
	  if( !verifySession(sessionVerificationData) ) {
		  // dont fail without session 
		  //return null;
	  }
	  
	  SnippetList result = new SnippetList();  
	  try{
		Connection cn = DBConnection.initializeConnection();
		Statement st = cn.createStatement();
		ResultSet rs = st.executeQuery("SELECT id FROM snippets");
		while(rs.next()) {
			int id = rs.getInt(1);
			result.add( id );
		}
	  }catch(Exception e){
		  e.printStackTrace();
	  }
	  return result;	
  }

  // TODO enhance?
  private boolean verifySession( SessionData.SessionVerificationData sessionVerificationData ) {
		System.out.println("Session "+sessionVerificationData .sessionID+" beeing veryfied");
		try{
			Connection cn = DBConnection.initializeConnection();
			PreparedStatement st = cn.prepareStatement("SELECT * FROM users " +
					"WHERE sessionID = ? AND sessionSecret = ?",
					ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, 0);
			st.setInt(1, sessionVerificationData .sessionID);
			st.setString(2, sessionVerificationData .sessionSecret);
			ResultSet rs = st.executeQuery();
			if(rs.next()){
				java.sql.Date now = new java.sql.Date( 	java.lang.System.currentTimeMillis()  );
				rs.updateDate("lastAction", now );
				rs.updateRow();
				return true;
			} else {
				return false;
			}
		} catch( Exception e ){
			e.printStackTrace();
			return false; // fail safe
		}
  }
	public SessionData syncSession(SessionData session){
		System.out.println("Session sync request");
		try{
			if(!session.loginRequestName.isEmpty()) {
				// try login
				Connection cn = DBConnection.initializeConnection();
				PreparedStatement st = cn.prepareStatement("SELECT * FROM users " +
						"WHERE name = ? AND pwdHash = ?",
						ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, 0);
				st.setString(1, session.loginRequestName);
				st.setString(2, session.loginRequestPasswordHash);
				ResultSet rs = st.executeQuery();
				if(rs.next()){
					// login data is correct
					session.userID = rs.getInt("id");
					session.sessionID = session.userID;
					session.emailAddress = rs.getString("email");
					 // TODO enhance:
					session.sessionSecret = Hash.hashContent(Integer.toString(session.sessionID));
					rs.updateInt("sessionID", session.sessionID);
					rs.updateString("sessionSecret", session.sessionSecret);
					rs.updateRow(); // store session id + secret back to db
					session.trustLevel = rs.getInt("trustLevel");
					session.userName = rs.getString("name");
				} else {
					// TODO ev. other fallback response
					return null;
				}
			}else{
				// not a login
			}		
			return session;
		} catch( Exception e ){
			e.printStackTrace();
			return null;
		}
	}
}
